自定义DataSource
类型的@Bean
可以覆盖默认设置,正如Section 24.7.1, “Third-party configuration”解释的那样,你可以很轻松的将它跟一系列Environment
属性绑定:
@Bean
@ConfigurationProperties(prefix="datasource.fancy")
public DataSource dataSource() {
return new FancyDataSource();
}
datasource.fancy.jdbcUrl=jdbc:h2:mem:mydb
datasource.fancy.username=sa
datasource.fancy.poolSize=30
Spring Boot也提供了一个工具类DataSourceBuilder
用来创建标准的数据源。如果需要重用DataSourceProperties
的配置,你可以从它初始化一个DataSourceBuilder
:
@Bean
@ConfigurationProperties(prefix="datasource.mine")
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder()
// additional customizations
.build();
}
在此场景中,你保留了通过Spring Boot暴露的标准属性,通过添加@ConfigurationProperties
,你可以暴露在相应的命命名空间暴露其他特定实现的配置,
具体详情可参考'Spring Boot特性'章节中的Section 29.1, “Configure a DataSource”和DataSourceAutoConfiguration类源码。
创建多个数据源和创建一个工作都是一样的,如果使用JDBC或JPA的默认自动配置,你需要将其中一个设置为@Primary
(然后它就能被任何@Autowired
注入获取)。
@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
Spring Data可以为你的@Repository
接口创建各种风格的实现。Spring Boot会为你处理所有事情,只要那些@Repositories
接口跟你的@EnableAutoConfiguration
类处于相同的包(或子包)。
对于很多应用来说,你需要做的就是将正确的Spring Data依赖添加到classpath下(JPA对应spring-boot-starter-data-jpa
,Mongodb对应spring-boot-starter-data-mongodb
),创建一些repository接口来处理@Entity
对象,相应示例可参考JPA sample或Mongodb sample。
Spring Boot会基于它找到的@EnableAutoConfiguration
来尝试猜测你的@Repository
定义的位置。想要获取更多控制,可以使用@EnableJpaRepositories
注解(来自Spring Data JPA)。
@Entity
定义Spring Boot会基于它找到的@EnableAutoConfiguration
来尝试猜测@Entity
定义的位置,想要获取更多控制可以使用@EntityScan
注解,比如:
@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {
//...
}
Spring Data JPA已经提供了一些独立的配置选项(比如,针对SQL日志),并且Spring Boot会暴露它们,针对hibernate的外部配置属性也更多些,最常见的选项如下:
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.database=H2
spring.jpa.show-sql=true
ddl-auto
配置是个特殊情况,它的默认设置取决于是否使用内嵌数据库(是则默认值为create-drop
,否则为none
)。当本地EntityManagerFactory
被创建时,所有spring.jpa.properties.*
属性都被作为正常的JPA属性(去掉前缀)传递进去了。
Spring Boot提供一致的命名策略,不管你使用什么Hibernate版本。如果使用Hibernate 4,你可以使用spring.jpa.hibernate.naming.strategy
进行自定义;Hibernate 5定义一个Physical
和Implicit
命名策略:Spring Boot默认配置SpringPhysicalNamingStrategy
,该实现提供跟Hibernate 4相同的表结构。如果你情愿使用Hibernate 5默认的,可以设置以下属性:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
具体详情可参考HibernateJpaAutoConfiguration和JpaBaseConfiguration。
为了完全控制EntityManagerFactory
的配置,你需要添加一个名为entityManagerFactory
的@Bean
,Spring Boot自动配置会根据是否存在该类型的bean来关闭它的实体管理器(entity manager)。
即使默认的EntityManagerFactory
工作的很好,你也需要定义一个新的EntityManagerFactory
,因为一旦出现第二个该类型的bean,默认的将会被关闭。为了轻松的实现该操作,你可以使用Spring Boot提供的EntityManagerBuilder
,或者如果你喜欢的话可以直接使用来自Spring ORM的LocalContainerEntityManagerFactoryBean
。
示例:
// add two data sources configured as above
@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(customerDataSource())
.packages(Customer.class)
.persistenceUnit("customers")
.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(orderDataSource())
.packages(Order.class)
.persistenceUnit("orders")
.build();
}
上面的配置靠自己基本可以运行,想要完成作品你还需要为两个EntityManagers
配置TransactionManagers
。其中的一个会被Spring Boot默认的JpaTransactionManager
获取,如果你将它标记为@Primary
。另一个需要显式注入到一个新实例。或你可以使用一个JTA事物管理器生成它两个。
如果使用Spring Data,你需要相应地需要配置@EnableJpaRepositories
:
@Configuration
@EnableJpaRepositories(basePackageClasses = Customer.class,
entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration {
...
}
@Configuration
@EnableJpaRepositories(basePackageClasses = Order.class,
entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration {
...
}
Spring不要求使用XML配置JPA提供者(provider),并且Spring Boot假定你想要充分利用该特性。如果你倾向于使用persistence.xml
,那你需要定义你自己的id为entityManagerFactory
的LocalEntityManagerFactoryBean
类型的@Bean
,并在那设置持久化单元的名称,默认设置可查看JpaBaseConfiguration。
Spring Data JPA和Spring Data Mongo都能自动为你创建Repository
实现。如果它们同时出现在classpath下,你可能需要添加额外的配置来告诉Spring Boot你想要哪个(或两个)为你创建仓库。最明确地方式是使用标准的Spring Data @Enable*Repositories
,然后告诉它你的Repository
接口的位置(此处*
即可以是Jpa,也可以是Mongo,或者两者都是)。
这里也有spring.data.*.repositories.enabled
标志,可用来在外部配置中开启或关闭仓库的自动配置,这在你想关闭Mongo仓库但仍使用自动配置的MongoTemplate
时非常有用。
相同的障碍和特性也存在于其他自动配置的Spring Data仓库类型(Elasticsearch, Solr),只需要改变对应注解的名称和标志。
Spring Data REST能够将Repository
的实现暴露为REST端点,只要该应用启用Spring MVC。Spring Boot暴露一系列来自spring.data.rest
命名空间的有用属性来定制化RepositoryRestConfiguration,你可以使用RepositoryRestConfigurer
提供其他定制。
如果想配置一个JPA使用的组件,你需要确保该组件在JPA之前初始化。组件如果是Spring Boot自动配置的,Spring Boot会为你处理。例如,Flyway是自动配置的,Hibernate依赖于Flyway,这样Hibernate有机会在使用数据库前对其进行初始化。
如果自己配置组件,你可以使用EntityManagerFactoryDependsOnPostProcessor
子类设置必要的依赖,例如,如果你正使用Hibernate搜索,并将Elasticsearch作为它的索引管理器,这样任何EntityManagerFactory
beans必须设置为依赖elasticsearchClient
bean:
/**
* {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that
* {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean.
*/
@Configuration
static class ElasticsearchJpaDependencyConfiguration
extends EntityManagerFactoryDependsOnPostProcessor {
ElasticsearchJpaDependencyConfiguration() {
super("elasticsearchClient");
}
}